package example03;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**
 *
 * @author
 */
public class MyList implements List<String> {

    private String array[] = new String[10];
    private int index = -1;
    private static final String INDEX_OUT_OF_BOUDS_MESSAGE = "Индекс выходит за пределы массива ";
    private static final String WRONG_INDEX_MESSAGE = "Начальный индекс больше конечного "; 
    private static int expand_array = 10;
    
    @Override
    public int size() {
        //Вернуть количество элементов в листе
        return index + 1;
    }

    @Override
    public boolean isEmpty() {
        // истина, если нет ни одного элемента
        if(index == -1){
            return true;
        }
        else{
            return false;
        }
    }

    @Override
    public boolean contains(Object o) {
        //Сравниваем на совпадение вот так. Только не забудь проверить, что о не null
        if(o != null){
            for(int i = 0; i < size(); i++){
                if(o.equals(array[i])){
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean add(String e) {
        // Добавляем в коллекцию элемент
        if(index == array.length - 1) {
            String temp[] = new String[array.length + expand_array];
            System.arraycopy(array, 0, temp, 0, size());
            array = temp;
            array[++index] = e;
        }
        else {
            array[++index] = e;
        }
        return true;
    }

    @Override
    public boolean remove(Object o) {
        // удаляем елемент, если такой есть там, возвращаем истину, если удали.
       int i;
       for(i = 0; i < size(); i++){
           if(o.equals(array[i])){                          
              remove(i);
              break;
           }
       }
       if(i < size()){
           return true;
       }       
       else{
           return false;
       }
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        //содержатся ли в нашем листе все элементы, которые есть в коллекции
        //перебираем коллекцию вот так:
        int check_index_1 = 0, check_index_2 = 0;
        for (Object o : c) {
            check_index_1++;
        }
        for (Object o : c){
            for(int i = 0; i < size(); i++){
                if(o.equals(array[i])){
                    check_index_2++;
                    break;
               }
            }
        }
        if(check_index_1 == check_index_2){
            return true;
        }
        else{
            return false;
        }
    }

    @Override
    public boolean addAll(Collection<? extends String> c) {
        // Добавляем коллекцию элементов
        for (String s : c) {
            add(s);            
        }
        return true; 
    }

    @Override
    public boolean addAll(int index, Collection<? extends String> c) {
        //добавляем коллекцию элементов, начиная с какого-то индекса
        if(index > array.length) {
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
        }
        for(String s : c){
            add(index, s);
            index++;
        }
        return true;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
       // удаляем элементы, если они есть в нашем листе      
       int check_index = index++;
       for(Object o : c){
           for(int j = 0; j < size(); j++){
               for(int i = 0; i < size(); i++){
                   if(o.equals(array[i])){
                       remove(i);
                   }
               }
           }
       }
       if(check_index == size()){
           return false;
       }
       else{
           return true;
       }
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        //оставляем в нашем листе только те элементы, которые есть в коллекции, которую мы передали.
        //то есть находим пересечение нашего листа и другой коллекции, и оставляем его в листе
        int index = -1;
        String temp[] = new String[array.length];
        for(int i = 0; i < size(); i++){
            for(Object s : c){
                if(s.equals(array[i])){
                    temp[++index] = array[i];
                }
            }
        }
        array = temp;
        this.index = index;
        return true;
    }

    @Override
    public void clear() {
        //очищаем лист
        index = -1;
    }

    @Override
    public String get(int index) {
        //возвращаем элемент по индексу
        if(index > array.length) {
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
        }
        String get = array[index];
        return get;
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String set(int index, String element) {
        if(index > array.length) {
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
        }
        array[index] = element;
        return element;
    }

    @Override
    public void add(int index, String element) {
        // добавляем по заданному индексу элемент, но ничего не затираем, а сдвигаем следующие элементы на 1 вперед
        if(index > array.length) {
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
        }
        String temp_1[] = new String[array.length];        
        int k = index + 1;
        System.arraycopy(array, 0, temp_1, 0, index);
        temp_1[index] = element;
        for(int i = index; i < array.length; i++) {
            if(k == array.length - 1) {
            String temp_2[] = new String[array.length + expand_array];
            System.arraycopy(temp_1, 0, temp_2, 0, array.length);
            temp_1 = temp_2;
            temp_1[k++] = array[i];
            
        }
        else {
            temp_1[k++] = array[i];
            }
        }
        array = temp_1;
        this.index++;
    }

    @Override
    public String remove(int index) {
        // удаляем элемент по индексу
       if(index > size()){
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
       }
       String result = array[index];
       System.arraycopy(array, ++index, array, --index, array.length - ++index);
       this.index--; 
       return result;
    }

    @Override
    public int indexOf(Object o) {
        //если в коллекции есть такой элемент, возвращаем его индекс (первого найденного)
        int index = -1;
        for(int i = 0; i < size(); i++){
            if(o.equals(array[i])){
                index = i;
                break;
            }
        }
        return index;
    }

    @Override
    public int lastIndexOf(Object o) {
        //индекс последнего найденного элемента
        int index = -1;
        if(o != null){
        for(int i = 0; i < size(); i++){
            if(o.equals(array[i])){
                index = i;
            }
        }
        }
        return index;
    }

    
    @Override
    public List<String> subList(int fromIndex, int toIndex) {
        //возвращаем подмножество этого листа
        if(fromIndex > array.length) {
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
        }
        if(toIndex > array.length) {
            throw new IndexOutOfBoundsException(INDEX_OUT_OF_BOUDS_MESSAGE);
        }
        if(fromIndex > toIndex) {
            throw new IndexOutOfBoundsException(WRONG_INDEX_MESSAGE);
        }
        List<String> temp = new ArrayList<>();
        for(int i = fromIndex; i < toIndex; i++){
            temp.add(array[i]);
        }
        return temp;
    }
    
    @Override
    public String toString() {
        String str = "[";
        for(int i = 0; i < size(); i++){
            str += (array[i]);
            if(i < size() - 1){
                str += ", ";
            }
        }
        str += "]";
        return str;
    }
    
    @Override
    public Iterator<String> iterator() {
        //возвращаем итератор, он нужен чтобы мы могли потом обращаться к нашему листу в цикле for each.
        //в этот метод ничего уже не надо дописывать, надо только реализовать класс MyIterator
        return new MyIterator(this);
    }
    
    //итератор позволяет пройти по коллекции с помощью методов hasNest() �? next()
    private class MyIterator implements Iterator<String> {
        
        private int index;
               
        public MyIterator(MyList list) {
            //конструктор принимает на вход наш лист, храним ссылку на него внутри класса
        }

        @Override
        public boolean hasNext() {             
            return index < size();
        }

        @Override
        public String next() {
            return array[index++];
        }

        @Override
        public void remove() {
            System.arraycopy(array, ++index, array, index, array.length - index);
        }
        
    }
    
    /*
     * Еще несколько моментов:
     * 
     * Когда мы в методе передаем индекс, если он у нас выходит за пределы массива,
     * нужно бросить исключение, пишем throw new IndexOutOfBoundsException("какое-то сообщение");
     * То есть наша программа упадет с ошибкой, и там будет выводится тот текст ошибки, который мы напишем.
     * 
     * throw new UnsupportedOperationException("Not supported yet."); во всех методах, которые будем реализовывать -
     * убираем.
     * 
     * Лист может хранить нулы, елинственное, нужно проверять на нулл объекты, если будешьл вызывать для них метод 
     * equals()
     *
     */
    
    //Оставшиеся методы не реализуем.
    
       
    @Override
    public ListIterator<String> listIterator() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public ListIterator<String> listIterator(int index) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
     
      @Override
    public Object[] toArray() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public <T> T[] toArray(T[] a) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
